home *** CD-ROM | disk | FTP | other *** search
- /*
- Experiments in reading a TIFF file
-
- */
- /* In this routine I prompt the user for the name of a TIFF file
- If the user gives me a valid name, I will treat the file as a
- TIFF file and interpret the records accordingly. I am trusting
- the user to have given me the name of a TIFF file and not the
- name of some other type of file. Once I have the name of the file
- I read in the TIFF data and then construct an off screen CGrafPort.
- the CGrafPort is very easy to create on a Macintosh and it solves
- many problems dealing with scrolling and color.
-
- The fun part of this code is where I create the Color Table and use
- that to create a Color Palette.
- You should read up on the palette manager in InsideMac Vol 5 and
- then play around with the code to see the different effects that
- you can accomplish.
- */
-
-
- #include "my color.h"
- #include "tiff.h"
- #include <StdFilePkg.h>
- #include <FileMgr.h>
- #define DOTS_PER_INCH_72 0x00480000
- CGrafPtr read_tiff_file(new_window)
- CWindowPtr new_window;
- {
- OSErr io_errors;
- char *my_prompt;
- Point cornor_of_dialog_box;
- register short even_constant, i;
- short file_ref_num, number_of_file_types, nBits;
- long header_size;
- long value, pixels_per_line, nLines, picture_size;
- char *PicbaseAddr;
- SFReply the_responce_to_me;
- SFTypeList my_type;
- PixMapHandle tiff_map;
- short max_value, min_value, photo_type, response_curve, response_unit, number_of_pm_entries;
- CTabHandle color_table;
- PaletteHandle picture_palette, window_palette;
- CGrafPtr the_picture;
- long next_IFD_offset, offset_to_the_image;
- short program_resource, TIFF_res_file, number_of_clut;
- CTabHandle the_clut_to_use;
- RGBColor rgb_black, rgb_white;
- Rect tempRect;
-
- color_table = 0L; /* initialize the important Ptrs/Handles to zero */
- tiff_map = 0L;
- the_picture = 0L;
- PicbaseAddr = 0L;
-
-
- rgb_black.red = rgb_black.green = rgb_black.blue = 0x0000;
- rgb_white.red = rgb_white.green = rgb_white.blue = 0xFFFF;
-
- tiff_map = (PixMapHandle)NewHandle(sizeof(PixMap)); /* get RAM for the PixMap */
- if(!tiff_map) return (CGrafPtr)0L; /* if I failed, return a NULL pointer */
-
- cornor_of_dialog_box.h = 50; /* draw the SFGetFile dialog at this point */
- cornor_of_dialog_box.v = 50;
- my_prompt = "\pWhere is TIFF?";
-
- number_of_file_types = 1;
- my_type[0] = 'TIFF';
-
- SFGetFile(cornor_of_dialog_box, my_prompt, (ProcPtr)0, number_of_file_types, my_type,
- (ProcPtr)0, &the_responce_to_me);
-
- if(!the_responce_to_me.good) return 0l; /* If the user didn't want to open a file with this window, return a NULL pointer */
- SetWTitle(new_window, the_responce_to_me.fName);
- io_errors = FSOpen(the_responce_to_me.fName, the_responce_to_me.vRefNum,
- &file_ref_num); /* Open the chosen TIFF file */
-
- header_size = (long)sizeof(tiff_header);
- io_errors = FSRead(file_ref_num, &header_size, &tiff_header); /* read the TIFF header */
-
- io_errors = SetFPos(file_ref_num, fsFromStart, tiff_header.first_IFD); /* read in the first IFD */
- header_size = (long)sizeof(number_of_directories);
- io_errors = FSRead(file_ref_num, &header_size, &number_of_directories); /* read how many image directories there are in the TIFF file */
-
- header_size = (long)sizeof(tiff_directory);
-
- ifd = (struct directory_entry *)NewPtr((long)sizeof(tiff_directory)); /* get some RAM for the IFD */
-
- if(tiff_header.first_IFD > 0)
- min_value = 0; /* the default minimum value */
- max_value = 256; /* the default maximum value */
- photo_type = 0; /* the default photo metric interpretation */
-
- for(i=0; i < number_of_directories; i++)
- {
- header_size = (long)sizeof(tiff_directory); /* the size of a IFD record */
- io_errors = FSRead(file_ref_num, &header_size, ifd); /* read the IFD */
- if(ifd->type == SHORT)
- value = (long)ifd->tag_value.short_value;
- else if(ifd->type == LONG)
- value = ifd->tag_value.long_value;
-
- switch(ifd->tag) /* decipher the TAG */
- {
- case SubFileType:
- break;
-
- case ImageWidth:
- pixels_per_line = value;
- break;
-
- case ImageLength:
- nLines = value;
- break;
-
- case BitsPerSample:
- nBits = value;
- min_value = 0;
- max_value = 256;
- break;
-
- case MaxSampleValue:
- max_value = value;
- break;
-
- case MinSampleValue:
- min_value = value;
- break;
-
- case PhotometricInterpretation:
- photo_type = value;
- break;
-
- case GrayResponseUnit:
- response_unit = value;
- break;
-
- case GrayResponseCurve:
- response_curve = value;
- break;
-
- case StripOffsets:
- offset_to_the_image = value;
- }
- }
-
- header_size = (long)sizeof(long);
- io_errors = FSRead(file_ref_num, &header_size, &next_IFD_offset); /* read how many image directories there are in the TIFF file */
-
- the_picture = (CGrafPtr)NewPtr(sizeof(CGrafPort)); /* Get RAM for the color graf port */
- if(!the_picture)
- {
- SysBeep(10);
- if(color_table) DisposHandle(color_table);
- if(tiff_map) DisposHandle(tiff_map);
- if(the_picture) DisposPtr(the_picture);
- if(PicbaseAddr) DisposPtr(PicbaseAddr);
- return (CGrafPtr)0L;
- }
-
- /* now I'll go ahead and open the file and read it in */
-
- picture_size = pixels_per_line * nLines;
- PicbaseAddr = NewPtr(picture_size); /* get enough RAM to hold The TIFF picture */
- if(!PicbaseAddr) /* If I don't suceed then quit */
- {
- SysBeep(10);
- DisposHandle(tiff_map);
- DisposPtr(the_picture);
- return (CGrafPtr)0L;
- }
-
- /* tiff_map is a CGrafPort, here is were many parameters are set
- based on what I read in from the TIFF file */
- (**tiff_map).baseAddr = PicbaseAddr;
- (**tiff_map).pixelSize = nBits;
- (**tiff_map).rowBytes = pixels_per_line | 0x8000;
- (**tiff_map).bounds.top = 0;
- (**tiff_map).bounds.left = 0;
- (**tiff_map).bounds.bottom = nLines;
- (**tiff_map).bounds.right = pixels_per_line;
- (**tiff_map).pixelType = 0;
- (**tiff_map).hRes = DOTS_PER_INCH_72;
- (**tiff_map).vRes = DOTS_PER_INCH_72;
- (**tiff_map).cmpCount = 1;
- (**tiff_map).cmpSize = (**tiff_map).pixelSize;
- (**tiff_map).planeBytes = 0;
- (**tiff_map).pmReserved = 0;
-
- /*
- ============================== Creating the clut ================================
- */
- /* Some TIFF files created on Macintosh computers will have a clut resource, lets see if this TIFF file does! */
-
- program_resource = CurResFile(); /* lets remember which resfile is being used before we change it!! */
-
- TIFF_res_file = OpenRFPerm(the_responce_to_me.fName, the_responce_to_me.vRefNum, fsRdPerm);
- if((number_of_clut = Count1Resources('clut')) == 0)
- {
- /* ******************************************************************************* */
- /* If I fell through to here then there isn't a clut Resource!
-
- Create the Color Table from the TIFF parameters
- */
- UseResFile(program_resource); /* reset the resource back to the program */
- color_table = (CTabHandle)NewHandle((Size)(sizeof(ColorTable) +
- (sizeof(ColorSpec) * (max_value - min_value)))); /* get RAM for the color TABLE */
- if(!color_table)
- {
- SysBeep(10);
- if(color_table) DisposHandle(color_table);
- if(tiff_map) DisposHandle(tiff_map);
- if(the_picture) DisposPtr(the_picture);
- if(PicbaseAddr) DisposPtr(PicbaseAddr);
- return (CGrafPtr)0L;
- }
- (**color_table).ctSeed = GetCTSeed();
- (**color_table).ctFlags = 0;
- (**color_table).ctSize = (short)(max_value - min_value);
- number_of_pm_entries = (short)(max_value - min_value);
- /* Now I'm going to create a color Table with Gray Scale values,
- most likely there will be 256 entries, but the number of entries
- actually depends of the max_value I read in from the TIFF file */
-
- even_constant = 65535 / (max_value - min_value); /* I will evenly space the grayscale values through the color table */
- if(photo_type == 1) /* photo type is a value I read from the TIFF
- file. If its value is 1, then the gray
- colors are ascending, and the picture looks
- like a normal black and white photo. If
- photo_type was 0 (Zero) then the gray scale
- values are decending, and the picture looks
- like a black and white negative! */
- for(i= 0; i < max_value; i++)
- { /* change these values to get really interesting
- effects, like multiply red by 2 and green by
- 4 and see what happens */
- (**color_table).ctTable[i].value = i;
- (**color_table).ctTable[i].rgb.red = (i * even_constant);
- (**color_table).ctTable[i].rgb.green = (i * even_constant);
- (**color_table).ctTable[i].rgb.blue = (i * even_constant);
- }
- else if(photo_type == 0)
- for(i= max_value; i > 0; i--)
- {
- (**color_table).ctTable[i].value = max_value - i;
- (**color_table).ctTable[i].rgb.red = (i * even_constant);
- (**color_table).ctTable[i].rgb.green = (i * even_constant);
- (**color_table).ctTable[i].rgb.blue = (i * even_constant);
- }
- }
- /* ******************************************************************************** */
- else /* A resource fork exists with a clut! Lets read it in! */
- { /* to experiment, try using ResEdit to paste a "clut"
- resource into the TIFF file you're reading, this
- program will then use that clut to create the Palette,
- This is a quick way to give your TIFF pictures a "false"
- color representation! */
- color_table = (CTabHandle)Get1IndResource('clut', 1);/* just get the "FIRST" clut to use */
- for(i = 0; i < (**color_table).ctSize; i++)
- (**color_table).ctTable[i].value = i; /* this is necessary for Color Quick
- has to know what colors go with
- what 8 bit values in the TIFF
- file */
- number_of_pm_entries = (**color_table).ctSize;
- UseResFile(program_resource);
- }
- /* now here is where the color palette is created, the palette is used
- to give the window the colors that are to be used in displaying the
- TIFF picture.
- */
- picture_palette = NewPalette(number_of_pm_entries, color_table,
- pmTolerant, 0x0000); /* trying changing pmTolerant parameter to
- something else ( see Inside Mac vol 5)
- and see what happens. The 0x0000 tells
- the palette manager to make exact matches
- to display the colors on screen
- */
- if(!picture_palette) /* if i couldn't get enought RAM for the palette, bail out! */
- {
- SysBeep(10);
- if(color_table) DisposHandle(color_table);
- if(tiff_map) DisposHandle(tiff_map);
- if(the_picture) DisposPtr(the_picture);
- if(PicbaseAddr) DisposPtr(PicbaseAddr);
- return (CGrafPtr)0L;
- }
-
- SetEntryColor(picture_palette, 0, &rgb_black); /* according to Inside Mac Vol 5,
- the first two colors in the
- palette should be black and
- white, this tells the
- palette manager which
- positions to use for
- those colors. See page V 158 in Inside Mac */
- SetEntryColor(picture_palette, 1, &rgb_white);
- SetEntryUsage(picture_palette, 0, 0x0000, 0x0000);
- SetEntryUsage(picture_palette, 1, 0x0002, 0x0000);
-
-
- HLock(color_table);
- (**tiff_map).pmTable = color_table; /* stick our color table into the palette! */
- HUnlock(color_table);
-
- /*
- =================================================================================
- */
- GetPort(&savedPort); /* SAVE THE CURRENT P0RT */
- OpenCPort(the_picture); /* now make our CGrafPort the default port */
- InitCPort(the_picture); /* initialize our CGrafPort to the default values */
-
- PmForeColor(1); /* here I tell the Palette Manager which colors to use for the foreground and background drawing */
- PmBackColor(0);
-
- SetPort(the_picture); /* make my offscreen CGrafPort the default port */
- SetPortPix(tiff_map); /* now make the PixMap I've created be the CGrafPort's PixMap */
-
- SetPort(savedPort);
-
- window_palette = GetPalette(new_window); /* if the window already has a palette, then get rid of it */
- if(window_palette)
- DisposePalette(window_palette);
- SetPalette(new_window, picture_palette, TRUE); /* make our palette the window's palette, the TRUE
- parameter tells the Mac that I want update
- events generated whenever the window's
- palette changes, for fun try changing it to
- FALSE */
- ActivatePalette(new_window); /* now turn on the palette */
-
- SetPort(new_window);
- /*
- now read in the TIFF picture and stick
- it into the offscreen CGrafPort, the
- update routine will take care of
- displaying the image
- */
- io_errors = SetFPos(file_ref_num, fsFromStart, offset_to_the_image); /* read in the first IFD */
- io_errors = FSRead(file_ref_num, &picture_size, PicbaseAddr);
- io_errors = FSClose(file_ref_num);
-
- DisposPtr(ifd); /* clean up after yourself */
- return the_picture;
- }